package com.ushine.design.jdk8.stream;
/**
 * @author yls
 * <p>
 * <p>
 * ==》jdk1.8 API 添加了一个新的抽象称为liuStream,可以用一种声明的方式处理数据。
 * 1）、Stream使用一种类似用哪个SQL语句从数据库查询的直观方式来提供一种对java集合运算和表达的高阶抽象。
 * 2）、Stream可以极大的提高java程序员的生产了，让程序员写成高效率、干净、简洁的代码。
 * 3）、可以把元素集合看作一种流，流在管道中传输，并且可以在管道的节点上进行处理、比如筛选、排序、聚合等。
 * 4）、元素流在管道中经过中间操作的处理，最后由最终操作得到前面处理的结果。
 * +--------------------+          +--------+  +--------+  +-----+  +-------+
 * | stream of elements +--------->| filter +->| sorted +->| map +->|collect|
 * +--------------------+          +--------+  +--------+  +-----+  +-------+
 * <p>
 * ==》Stream(流)是一个来自数据源的元素队列并支持聚合操作
 * .元素是特定类型的对象，形成一个队列。java中的Stream并不会存储元素，而是按需计算。
 * .数据源：流的来源，可以是集合、数组、I/O channel，产品器generator等
 * .聚合操作：类似SQL语句一样的操作，比如filter,map,reduce,find,match,sorted等
 * 注意：除此之外，和以前的Collection操作不同，Stream操作还有两个基本的特征：
 * 。Pipelining中间操作都会返回流对象本身。这样多个操作可以串联成一个管道，如同流式风格。
 * 可以对操作优化，比如延迟执行和短路。
 * .内部迭代：以前对集合遍历都是通过Iterator或者Fot-Each的方式，显式的在集合外部迭代，
 * 这叫做外部迭代。而Stream通过访问者模式（Visitor）实现。
 */

import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

public class StreamOfFuntion {

    public static void main(String[] args) {
        /**
         * 1、两种方式生成流： stream()——为集合创建串行流。 parallelStream()——为集合创建并行流。
         */
        List<String> strings = Arrays.asList("abc", "", null, "das", "df", "safg");
        // 过滤null，过滤""。此处一定要注意先过滤null，后过滤""
        List<String> filtered = strings.stream().filter(string -> string != null).filter(string -> !string.isEmpty())
                .collect(Collectors.toList());
        filtered.forEach(System.out::println);

        /**
         * 2、For-Each来迭代流中的每个元素
         */
        Random random = new Random();
        random.ints().limit(10).forEach(System.out::println);

        /**
         * 3、map方法用于映射每个元素到对应的结果，以下代码片段使用map输出对应的平方数
         */
        List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
        // 获取对应的平方数
        List<Integer> squaresList = numbers.stream().map(i -> i * i).distinct().collect(Collectors.toList());
        squaresList.forEach(System.out::println);

        /**
         * 4、filter方法用于通过设置的条件过滤出元素
         */
        List<String> strs = Arrays.asList("abc", "", null, "das", "df", "safg");
        // 过滤null，过滤""。此处一定要注意先过滤null，后过滤""
        List<String> filtereds = strs.stream().filter(string -> string != null).filter(string -> !string.isEmpty())
                .collect(Collectors.toList());
        filtereds.forEach(System.out::println);

        /**
         * 5、limit方法用于获取指定数量的流
         */
        random.ints().limit(10).forEach(System.out::println);

        /**
         * 6、sorted方法用于对流进行排序。
         */
        random.ints().limit(10).sorted().forEach(System.out::println);

        /**
         * 7、parallelStream是流并行处理程序的代替方法
         */
        List<String> strsList = Arrays.asList("as", "ag", "", null, "sfasg", "asdgasdg", "jkl");
        //获取空字符串的数量
        long count = strsList.parallelStream().filter(str -> str == null || str.isEmpty()).count();
        System.out.println(count);

        /**
         * 8、Collectors类实现了很多归约操作，例如流转换成集合和聚合元素。Collectors可用于返回列表和字符串
         */
        List<String> stringsList = Arrays.asList("as", "ag", "", null, "sfasg", "asdgasdg", "jkl");
        List<String> nullStrList = strsList.parallelStream().filter(str -> str != null && !str.isEmpty()).collect(Collectors.toList());
        System.out.println("筛选列表为：" + nullStrList);
        String nullString = stringsList.stream().filter(str -> str != null && !str.isEmpty()).collect(Collectors.joining(","));
        System.out.println("合并的字符串：" + nullString);

        /**
         * 9、统计：一些统计结果的收集器也非常重要，主要用于int、double、long等基本类型上。可以用来产生类似的统计结果。
         */
        List<Integer> numbersList = Arrays.asList(1, 3, 5, 8, 9, 10, 1, 5);
        IntSummaryStatistics stats = numbersList.stream().mapToInt((x) -> x).summaryStatistics();
        System.out.println("列表中最大的数：" + stats.getMax());
        System.out.println("列表中最小的数：" + stats.getMin());
        System.out.println("所有数之和：" + stats.getSum());
        System.out.println("平均值：" + stats.getAverage());
        System.out.println(stats.getCount());
    }

}
